%{
#define YY_NO_UNISTD_H
#include "Parserbase.h"
#include <cstring>

#define VALUE_RET(type, value) std::cerr << "\e[0;36mreturning " << type << ": \"\e[1;31m" << value << "\e[0;36m\"\e[m" << std::endl
#define TYPE_RET(type) std::cerr << "\e[0;36mreturning " << type << "\e[m" << std::endl
%}

%option outfile="Scanner.cpp" header-file="Scanner.h"
%option c++ 8bit warn yywrap yylineno

 /*%start COMMENT */
%x STRING MCOMMENT

DIGIT               [0-9]
ALPHA               [A-Za-z]
ALPHANUM            {ALPHA}({DIGIT}|{ALPHA})*
NEWLINE             \n
WHITESPACE          [ \t]+
MCOMMENT_BEGIN       \/\*
MCOMMENT_END         \*\/

SCOMMENT            \/\/[^\n]*

STRING_DELIMITER    \"

IGNORED             {NEWLINE}|{WHITESPACE}|{SCOMMENT}
%%

{STRING_DELIMITER} {
    BEGIN STRING;
}

<STRING>\\. {
    // TODO: escape symbols here
    switch ( yytext[yyleng - 1] )
    {
    case 'n':
        yytext[yyleng - 2] = '\n';
        break;
    case '0':
        yytext[yyleng - 2] = '\0';
        break;
    case 't':
        yytext[yyleng - 2] = '\t';
        break;
    case '"':
        /*
         * FIXME: This crunch replaces " character with '
         */
        yytext[yyleng - 2] = '\'';
        break;
    default:
        yytext[yyleng - 2] = yytext[yyleng - 1];
    }

    for ( int i = yyleng - 2; i >= 0; i-- )
        unput(yytext[i]);
}

<STRING>[^"\\]* {
    yymore();
}

<STRING>{STRING_DELIMITER} {
    yytext[yyleng - 1] = '\0';
    VALUE_RET("STRING_CONST", yytext);
    BEGIN 0;
    return Parser::STRING_CONST;
}

{MCOMMENT_BEGIN} {
    BEGIN MCOMMENT;
}

<MCOMMENT>.|\n {
    // nothing!
}

<MCOMMENT>{MCOMMENT_END} {
    BEGIN 0;
}

{DIGIT}*\.{DIGIT}+ {
    VALUE_RET("FLOAT_CONST", yytext);
    return Parser::FLOAT_CONST;
}

{DIGIT}+ {
    VALUE_RET("INT_CONST", yytext);
    return Parser::INT_CONST;
}

; {
    TYPE_RET("SEMICOLON");
    return Parser::SEMICOLON;
}

{IGNORED} {
    //TYPE_RET("nothing");
}

import {
    TYPE_RET("IMPORT");
    return Parser::IMPORT;
}

as {
    TYPE_RET("AS");
    return Parser::AS;
}

id {
    TYPE_RET("OBJ_ID");
    return Parser::OBJ_ID;
}

{ALPHANUM} {
    VALUE_RET("ID", yytext);
    return Parser::ID;
}

. {
    VALUE_RET("misc", yytext[0]);
    return yytext[0];
}

%%

int yyFlexLexer::yywrap()
{
  return 1;
}

// int main()
// {
//   yyFlexLexer l;
//   return l.yylex();
// }
